package com.yunti.springboot.config.interceptor;

import com.alibaba.fastjson.JSON;
import com.yunti.springboot.annotation.Log;
import com.yunti.springboot.annotation.Permission;
import com.yunti.springboot.bo.UserBO;
import com.yunti.springboot.config.component.AbstractCurrentRequestComponent;
import com.yunti.springboot.config.log.ApiLogConfig;
import com.yunti.springboot.mapper.ApiLogMapper;
import com.yunti.springboot.po.ApiLog;
import com.yunti.springboot.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;


/**
 * @author qiweiqing
 */
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Resource
    private ApiLogMapper mapper;

    @Resource
    private AbstractCurrentRequestComponent abstractCurrentRequestComponent;

    static final String REQUEST_HEADER_TOKEN = "Authorization";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        log.info("开始进入OA地址拦截");
        String token = request.getHeader("Authorization");
        Result result = new Result(Result.UNLOGIN, "invalid ticket", "请登录后再操作哦~!");
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        try {
            UserBO currentStaffId = abstractCurrentRequestComponent.getCurrentStaffId();
            if (currentStaffId != null) {
                // 如果不是映射到方法直接通过
                if (!(object instanceof HandlerMethod)) {
                    return true;
                }
                HandlerMethod handlerMethod = (HandlerMethod) object;
                Method method = handlerMethod.getMethod();
                //检查是否有passkey注释，有则跳过认证
                if (method.isAnnotationPresent(Log.class)) {
                    ApiLogConfig.setLog(request,token,currentStaffId);
                }
                if (method.isAnnotationPresent(Permission.class)) {
                    Permission permission = method.getAnnotation(Permission.class);
                    List<String> roles = Arrays.asList(permission.value());
                    //如果两个集合没有公共的元素则返回true，否则返回false
                    if(roles!=null&&currentStaffId.getRank()!=null&&!Collections.disjoint(roles, currentStaffId.getRank())){
                        log.info("-----鉴权通过----");
                        return true;
                    }else {
                        result.setUserMsg("权限不足");
                        result.setMsg("permission error");
                        result.setCode(Result.NO_PERMISSIONS);
                        log.info("-----鉴权不通过，权限不足----");
                        response.getWriter().write(JSON.toJSONString(result));
                        return false;
                    }
                }
                return true;
            }
        } catch (Exception e) {
            log.warn("拦截器异常：" + e.getMessage());
            response.getWriter().write(JSON.toJSONString(result));
            return false;
        }
        response.getWriter().write(JSON.toJSONString(result));
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) {
        // TODO document why this method is empty
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return;
        }
        // 将handler强转化为handlebars
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 从方法处理器中获取要调用的方法
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(Log.class)) {
            Log ignoreLog =  method.getAnnotation(Log.class);
            if (!ignoreLog.required()) {
                return ;
            }
        }
        // 获取方法上的LoginInterceptor注解

            ApiLog a = (ApiLog) request.getAttribute(ApiLogConfig.APILOG_OBJ_SAVE_KEY);
            // 开始结束计时
            if (a == null) {
                return;
            }

            a.setEndTime(new Date());
            a.setCostTime(a.getEndTime().getTime() - a.getStartTime().getTime());
            a.setResCode("200");
            // 控制台日志
            log.info("----------------------------------------------------------------");
            log.info("IP: " + a.getReqIp() + "\tr-> " + a.getReqApi() + "\tp-> " + a.getReqParame());
            log.info("本次请求耗时：" + a.getCostTime()  + "ms, 返回：" + a.getResString());
            log.info("----------------------------------------------------------------");
            // res 字符串过长时禁止写入
            if(a.getResString()!=null&&a.getResString().length() > 50000) {
                a.setResString("{\"msg\": \"数据过长，无法写入 (length=" + a.getResString().length() + ")\"}");
            }
            mapper.insert(a);

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception ex) {
        // TODO document why this method is empty
    }
}
